#pragma once

#define med(val, _min, _max) (max(min(_max,val),_min))
//#define M_PI_F ((float)M_PI)

#define OFFSET_DRAWTEXT 0x004B7610

template <class T>
class Singleton
{
public:
	static T& Inst()
	{
		static T __Inst;
		return __Inst;
	}

private:
	Singleton();
	~Singleton();
	Singleton(Singleton const&);
	Singleton& operator=(Singleton const&);
};

class CDraw
{
public:

	void DrawTriangle2d(float x0, float y0,float x1, float y1,float x2, float y2,DWORD col);
	void FillRect(float x0, float y0, float x1, float y1, DWORD col);
	void DrawHealthBarVertical(float x0, float y0, float w, float h, float percentage);
	void DrawHealthBarHorizontal(float x0, float y0, float w, float h, float percentage);
	void FillRect1(float x, float y, float w, float h,DWORD col);
	void DrawEngText(int x, int y, DWORD col, char* text, float flsize);
	void DrawLine(float x0, float y0, float x1, float y1, DWORD col);
	void DrawLine2(float x0, float y0, float len, float angle, DWORD col);
	void DrawArrow(float x0, float y0, float len, float width, float angle, DWORD col);
	void DrawSphere(fb::Vec3 pos,float radius, DWORD col);
	void DrawRect2(float x, float y, float w, float h, DWORD col);
	void DrawRect(float x, float y, float w, float h, DWORD col);
};

#define Draw Singleton<CDraw>::Inst()

void CDraw::DrawHealthBarHorizontal(float x0, float y0, float w, float h, float percentage)
{
	FillRect1(x0,y0,w,-h,0xFF000000);
	DWORD dwColor=0xFF000000;
	JUNK_CODE;
	dwColor|=((DWORD)med(percentage*255.f,0.f,255.f))<<8;
	JUNK_CODE;
	dwColor|=((DWORD)med(255.f*(1.f-percentage),0.f,255.f));
	JUNK_CODE;
	FillRect1(x0+1,y0+1,w-2*percentage,-(h-2),dwColor);
}
void CDraw::DrawHealthBarVertical(float x0, float y0, float w, float h, float percentage)
{
	FillRect1(x0,y0,w,-h,0xFF000000);
	DWORD dwColor=0xFF000000;
	JUNK_CODE;
	dwColor|=((DWORD)med(percentage*255.f,0.f,255.f))<<8;
	JUNK_CODE;
	dwColor|=((DWORD)med(255.f*(1.f-percentage),0.f,255.f));
	FillRect1(x0+1,y0+1,w-2,-(h-2)*percentage,dwColor);
}

void CDraw::DrawLine2(float x0, float y0, float len, float angle, DWORD col)
{
	float x=(cos(angle)*len)+x0;
	JUNK_CODE;
	float y=(sin(angle)*len)+y0;
	JUNK_CODE;
	return DrawLine(x0,y0,x,y,col);
}

void CDraw::DrawArrow(float x, float y, float len, float width, float angle, DWORD col)
{
	float x0=(cos(angle)*len)+x;
	float y0=(sin(angle)*len)+y;
	float x1=(cos(angle+(M_PI_F/2.f))*width/2.f)+x;
	JUNK_CODE;
	float x2=(cos(angle-(M_PI_F/2.f))*width/2.f)+x;
	float y1=(sin(angle+(M_PI_F/2.f))*width/2.f)+y;
	JUNK_CODE;
	float y2=(sin(angle-(M_PI_F/2.f))*width/2.f)+y;
	float x01=(cos(angle)*(len+1.f))+x;
	float y01=(sin(angle)*(len+1.f))+y;
	float x11=(cos(angle+(M_PI_F/2.f))*(width/2.f+1.f))+x;
	float x21=(cos(angle-(M_PI_F/2.f))*(width/2.f+1.f))+x;
	JUNK_CODE;
	float y11=(sin(angle+(M_PI_F/2.f))*(width/2.f+1.f))+y;
	float y21=(sin(angle-(M_PI_F/2.f))*(width/2.f+1.f))+y;
	DrawTriangle2d(x01,y01,x11,y11,x21,y21,0xFF000000);
	DrawTriangle2d(x0,y0,x1,y1,x2,y2,col);
}

void CDraw::DrawTriangle2d(float x0, float y0,float x1, float y1,float x2, float y2,DWORD col)
{
	fb::DebugRenderer2* pDR=fb::DebugRenderer2::Singleton();
	if(!pDR)
	{
		return;
	}
	eastl::Tuple<float> t1, t2, t3;
	t1._1=x0;
	t1._2=y0;
	JUNK_CODE;
	t2._1=x1;
	t2._2=y1;
	t3._1=x2;
	JUNK_CODE;
	t3._2=y2;
	typedef void (__thiscall* tDrawSingleColorTriangle)(fb::DebugRenderer2*, eastl::Tuple<float>*, eastl::Tuple<float>*, eastl::Tuple<float>*,DWORD);
	JUNK_CODE;
	tDrawSingleColorTriangle m_DrawSingleColorTriangle=(tDrawSingleColorTriangle)0x004BD5F0;
	JUNK_CODE;
	m_DrawSingleColorTriangle(pDR,&t1,&t2,&t3,col);
}

void CDraw::FillRect(float x0, float y0, float x1, float y1, DWORD col)
{
	fb::DebugRenderer2* pDR=fb::DebugRenderer2::Singleton();
	if(!pDR)
	{
		return;
	}
	eastl::Tuple<float> t1,t2;
	t1._1=x0;
	t1._2=y0;
	JUNK_CODE;
	t2._1=x1;
	t2._2=y1;
	typedef void(__thiscall* tFillRect)(fb::DebugRenderer2*,eastl::Tuple<float>*, eastl::Tuple<float>*, DWORD);
	JUNK_CODE;
	tFillRect m_FillRect=(tFillRect)0x004BA4F0;
	m_FillRect(pDR,&t1,&t2,col);
}

void CDraw::FillRect1(float x, float y, float w, float h,DWORD col)
{
	return FillRect(x,y,x+w,y+h,col);
}

void CDraw::DrawEngText(int x, int y, DWORD col, char* text, float flsize)
{
	fb::DebugRenderer2* pDR=fb::DebugRenderer2::Singleton();
	JUNK_CODE;
	if(!pDR)
	{
		return;
	}
	JUNK_CODE;
	typedef void (__thiscall *tDrawText)(fb::DebugRenderer2*,int, int, char*, DWORD, float);
	JUNK_CODE;
	tDrawText EngDrawText=(tDrawText)OFFSET_DRAWTEXT;
	EngDrawText(pDR,x,y,text,col,flsize);
}

void CDraw::DrawLine(float x0, float y0, float x1, float y1, DWORD col)
{
	fb::DebugRenderer2* pDR=fb::DebugRenderer2::Singleton();
	if(!pDR)
	{
		return;
	}
	typedef void(__thiscall* tDrawLine2D)(fb::DebugRenderer2*,eastl::Tuple<float>*, eastl::Tuple<float>*, DWORD);
	JUNK_CODE;
	tDrawLine2D DrawLine2D=(tDrawLine2D)0x004B9980;
	JUNK_CODE;
	eastl::Tuple<float> t1,t2;
	t1._1=x0;
	t1._2=y0;
	t2._1=x1;
	JUNK_CODE;
	t2._2=y1;
	DrawLine2D(pDR,&t1,&t2,col);
}


void CDraw::DrawSphere(fb::Vec3 pos,float radius, DWORD col)
{
	fb::DebugRenderer2* pDR=fb::DebugRenderer2::Singleton();
	if(!pDR)
	{
		return;
	}
	__declspec(align(16)) fb::Vec3 _pos;
	_pos.x=pos.x;
	_pos.y=pos.y;
	JUNK_CODE;
	_pos.z=pos.z;
	_pos.w=pos.w;
	JUNK_CODE;
	typedef void(__thiscall* tDrawSphere)(fb::DebugRenderer2*,fb::Vec3*, float, DWORD, bool, bool);
	tDrawSphere DrawSphere=(tDrawSphere)0x004BA2C0;
	JUNK_CODE;
	DrawSphere(pDR,&_pos,radius,col,false,false);
}

void CDraw::DrawRect2(float x, float y, float w, float h, DWORD col)
{
	fb::DebugRenderer2* pDR=fb::DebugRenderer2::Singleton();
	if(!pDR)
	{
		return;
	}
	eastl::Tuple<float> t1,t2;
	t1._1=x;
	JUNK_CODE;
	t1._2=y;
	t2._1=x+w;
	t2._2=y+h;
	JUNK_CODE;
	typedef void(__thiscall* tDrawRect2D)(fb::DebugRenderer2*,eastl::Tuple<float>*, eastl::Tuple<float>*, DWORD);
	tDrawRect2D DrawRect2D=(tDrawRect2D)0x004BA2E0;
	JUNK_CODE;
	DrawRect2D(pDR,&t1,&t2,col);

}


void CDraw::DrawRect(float x, float y, float w, float h, DWORD col)
{
	DrawRect2(x,y,w,h,col);
	JUNK_CODE;
	DrawRect2(x-1,y+1,w+2,h-2,0xFF000000);
	JUNK_CODE;
	DrawRect2(x+1,y-1,w-2,h+2,0xFF000000);
	JUNK_CODE;
}


